﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Resources;
using TestApp.Flowchart.Model;

namespace TestApp.Flowchart
{
    public partial class FlowchartEditor : UserControl
	{
        private ItemsControlDragHelper _dragHelper;
        
        public FlowchartEditor()
		{
			InitializeComponent();                    
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            FillToolbox();

            _dragHelper = new ItemsControlDragHelper(_toolbox, this);

            new_file();
            updateTabIteName("未命名");
        }

        private void FillToolbox()
		{
            Uri uri = new Uri("pack://application:,,,/Resources/toolbox.json", UriKind.Absolute);

            StreamResourceInfo info = Application.GetResourceStream(uri);
            //读取资源文件
            StreamReader reader = new StreamReader(info.Stream, Encoding.UTF8);
            String content = reader.ReadToEnd();
            var toolBoxEntity = JSONUtils.Json2Obj<ToolBoxEntity>(content);
            Singleton.Instance().ToolBoxList = toolBoxEntity.ToolBoxList;

            reader.Close();

            foreach (var item in Singleton.Instance().ToolBoxList)
            {
                Type t = Type.GetType(item.FullName);
                var obj = t.Assembly.CreateInstance(item.FullName);

                var node = obj as FlowNode;
                StackPanel stackPanel = new StackPanel();
                stackPanel.Orientation = Orientation.Horizontal;
                stackPanel.Margin = new Thickness(5, 10, 0, 10);

                ImageBrush imageBrush = new ImageBrush();
                imageBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Resources/" + item.IconName, UriKind.Absolute));
                Image image = new Image();
                image.Source = imageBrush.ImageSource;
                image.Height = 30;
                image.Width = 30;
                stackPanel.Children.Add(image);

                var textBlock = new TextBlock()
                {
                    VerticalAlignment = VerticalAlignment.Center,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    Width = 70,
                    Height = 30,
                    Text = item.DisplayName,
                    Padding = new Thickness(10, 10, 0, 0),
                    TextAlignment = TextAlignment.Left,
                    FontSize = 10
                };
                stackPanel.Children.Add(textBlock);
                stackPanel.Tag = item.FullName;

                _toolbox.Items.Add(stackPanel);
            }            
		}        
        
		void Selection_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			var p = _editor.Selection.Primary;
			_propertiesView.SelectedObject = p != null ? p.ModelElement : null;
		}

        public void copy()
        {
            var p = _editor.Selection.Primary;
            if (p == null)
                return;

            FlowNode node = p.ModelElement as FlowNode;
            string tempJSON = JSONUtils.Obj2Json(node);

            Singleton.Instance().copy_object = tempJSON;
            Singleton.Instance().copy_type = node.FullName;
        }

        public void paste()
        {
            if (Singleton.Instance().copy_object == null)
                return;

            Type t = Type.GetType(Singleton.Instance().copy_type);
            var obj = t.Assembly.CreateInstance(Singleton.Instance().copy_type);

            MethodInfo methodInfo = t.GetMethod("Json2Obj");
            var result = methodInfo.Invoke(obj, new object[] { Singleton.Instance().copy_object }) as FlowNode;

            result.X += 10;
            result.Y += 10;

            (_editor.Controller as Controller).addModel(result);
        }

        public void undo()
        {
            if (Singleton.Instance().commandList.Count == 0)
                return;

            Controller controller = _editor.Controller as Controller;

            Command command = Singleton.Instance().commandList[Singleton.Instance().commandList.Count - 1];
            Singleton.Instance().commandList.Remove(command);

            if (command.type == CommandEnum.Add)
            {
                (_editor.Controller as Controller).deleteModelByGuid(command.guid);
            }
            else if (command.type == CommandEnum.Delete)
            {
                Type t = Type.GetType(command.fullname_of_model);
                var obj = t.Assembly.CreateInstance(command.fullname_of_model);

                MethodInfo methodInfo = t.GetMethod("Json2Obj");
                var result = methodInfo.Invoke(obj, new object[] { command.modelJSON }) as FlowNode;

                (_editor.Controller as Controller).addModel(result);
            }
            else //modify
            {
                Type t = Type.GetType(command.fullname_of_model);
                var obj = t.Assembly.CreateInstance(command.fullname_of_model);

                MethodInfo methodInfo = t.GetMethod("Json2Obj");
                var result = methodInfo.Invoke(obj, new object[] { command.modelJSON }) as FlowNode;

                (_editor.Controller as Controller).updateModel(result);
            }
        }

        void resetSingletion()
        {
            Singleton.Instance().commandList = new List<Command>();
            Singleton.Instance().copy_object = null;
            Singleton.Instance().copy_type = null;
            Singleton.Instance().save_file_name = null;
        }

        public void new_file()
        {
            resetSingletion();

            FlowchartModel model = new FlowchartModel();
            _editor.Controller = new Controller(_editor, model);
            _editor.DragDropTool = new DragDropTool(_editor, model);
            _editor.DragTool = new CustomMoveResizeTool(_editor, model)
            {
                MoveGridCell = _editor.GridCellSize
            };
            _editor.LinkTool = new CustomLinkTool(_editor);
            _editor.Selection.PropertyChanged += Selection_PropertyChanged;
        }

        public void updateTabIteName(string headerName)
        {
            tabitem1.Header = headerName;
        }

        public void loadModel(String strModel)
        {
            resetSingletion();

            var temp_model = JSONUtils.Json2Obj<ModelEntity>(strModel);
            var model = new FlowchartModel();

            foreach (var node in temp_model.Nodes)
            {
                var dic1 = JSONUtils.Json2Obj<Dictionary<string, object>>(node.ToString());
                var fullName = dic1["FullName"].ToString();

                Type t = Type.GetType(fullName);
                var obj = t.Assembly.CreateInstance(fullName);
                MethodInfo methodInfo = t.GetMethod("Json2Obj");
                var result = methodInfo.Invoke(obj, new object[] { node.ToString() }) as FlowNode;
                model.Nodes.Add(result);
            }

            _editor.Controller = new Controller(_editor, model);
            _editor.DragDropTool = new DragDropTool(_editor, model);
            _editor.DragTool = new CustomMoveResizeTool(_editor, model)
            {
                MoveGridCell = _editor.GridCellSize
            };
            _editor.LinkTool = new CustomLinkTool(_editor);
            _editor.Selection.PropertyChanged += Selection_PropertyChanged;
        }

        public string saveModel()
        {
            return (_editor.Controller as Controller).saveModel();           
        }

        public void moveLeft(int pixel)
        {
            if (_editor.Selection == null)
                return;

            if (_editor.Selection.Primary == null)
                return;

            if (_editor.Selection.Primary.ModelElement == null)
                return;

            var r = _editor.Selection.Primary.ModelElement as FlowNode;
            r.X -= pixel;            
        }

        public void moveUp(int pixel)
        {
            if (_editor.Selection == null)
                return;

            if (_editor.Selection.Primary == null)
                return;

            if (_editor.Selection.Primary.ModelElement == null)
                return;

            var r = _editor.Selection.Primary.ModelElement as FlowNode;
            r.Y -= pixel;
        }
    }
}
